﻿using System;
using System.Collections.Generic;
using System.Linq;
using demo1.Models.Database;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using StackExchange.Redis;
using demo1.Models;
using Ninject.Activation.Caching;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;

namespace demo1.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class RedisController : ControllerBase
    {
        private readonly IDatabase _redis;
        private readonly WebEnterpriseIIContext _db;
        public RedisController(RedisHelper client, WebEnterpriseIIContext db)
        {
            _db = db;
            //创建Redis连接对象
            _redis = client.GetDatabase();
        }
        [HttpGet]
        public void SetRedisCache()
        {
            _redis.StringSet("RedisCache", "6666");
        }
        [HttpGet]
        public void SerializeJSON()
        {
            //查询商品
            var good = _db.Goods.FirstOrDefault(x => x.Id == 10);
            //转化为json字符串
            var jsonStr = JsonConvert.SerializeObject(good);
            //json字符串保存到redis
            _redis.StringSet("goodinfo", jsonStr);
            //从redis取出json字符串
            var redisStr = _redis.StringGet("goodinfo");
            //转化为对象
            var jsonObj = JsonConvert.DeserializeObject<Good>(redisStr);
        }
        [HttpGet]
        public List<Good> GetGoodList()
        {
            var cache = _redis.StringGet("GoodCache");
            if (cache.HasValue)
            {
                var jsonObj = JsonConvert.DeserializeObject<List<Good>>(cache);
                //3、如果有则直接返回缓存数据
                return jsonObj;
            }
            else
            {
                //2、如果没有则去数据库查询并且把查询结果保存到缓存 缓存时间为30分钟
                var goods = _db.Goods.ToList();
                var jsonStr = JsonConvert.SerializeObject(goods);
                _redis.StringSet("GoodCache", jsonStr,new TimeSpan(0,30,0));
                return goods;
            }
        }
        [HttpGet]
        [Authorize]
        public Good GetGoodInfo(int goodId)
        {
            //商品详情
            var good = _db.Goods.FirstOrDefault(x => x.Id == goodId);
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            //之前缓存下来的浏览记录  每个用户浏览记录都是单独的 每个用户都有自己的key  UserViews28\UserViews20
            var recordStr = _redis.StringGet($"UserViews{userId}");
            var record = JsonConvert.DeserializeObject<List<Good>>(recordStr);
            //浏览商品记录
            var views = new List<Good>();
            views.Add(good); //永远只有刚刚看的这一条商品数据

            //是不是还应该有前面的数据
            if (record != null)
                views.AddRange(record); //我前面看过的数据

            var jsonStr = JsonConvert.SerializeObject(views);
            _redis.StringSet($"UserViews{userId}", jsonStr);
            return good;
        }
        [HttpGet]
        [Authorize] //授权
        public Good GetGoodInfo1(int goodId)
        {
            //商品详情
            var good = _db.Goods.FirstOrDefault(x => x.Id == goodId);

            //使用本地缓存保存登录用户浏览商品记录(多个商品)
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;

            //使用redis取代本地缓存
            ////之前缓存下来的浏览记录  每个用户浏览记录都是单独的 每个用户都有自己的key  UserViews28\UserViews20
            var key = $"UserViews{userId}";

            //在用户浏览商品的时候 添加商品浏览记录 商品
            //新数据在左边还是右边
            //最近浏览的商品
            //新 旧

            var jsonStr = JsonConvert.SerializeObject(good);//序列化
            _redis.ListLeftPush(key, jsonStr);// 1 1 1

            return good;
        }
        [HttpGet]
        [Authorize] //授权
        public Good GetGoodInfo2(int goodId)
        {
            //商品详情
            var good = _db.Goods.FirstOrDefault(x => x.Id == goodId);

            //使用本地缓存保存登录用户浏览商品记录(多个商品)
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;

            //使用redis取代本地缓存
            ////之前缓存下来的浏览记录  每个用户浏览记录都是单独的 每个用户都有自己的key  UserViews28\UserViews20
            var key = $"UserViews{userId}";

            //记录商品浏览时间 把分数和时间关联
            //在用户浏览商品的时候 添加商品浏览记录 商品 
            //新数据在左边还是右边
            //最近浏览的商品
            //新 旧

            //浏览商品时间的时间戳 1970年1月1日 0时0分0秒(北京时间要加8个小时) 到现在的时间 就是时间戳
            var score = (DateTime.Now - new DateTime(1970, 1, 1, 8, 0, 0)).TotalSeconds;

            var jsonStr = JsonConvert.SerializeObject(good);//序列化
            _redis.SortedSetAdd(key, jsonStr, score);// 1 1 1

            //以浏览时间为分数的 商品数据 
            //1、获取到最新的浏览商品记录
            //2、获取到商品浏览时间

            //数据类型的使用实战技巧

            return good;
        }
        [HttpGet]
        [Authorize]
        public string AddCar(int goodid)
        {
            var userid = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            var key = "car_" + userid;
            _redis.HashIncrement(key, goodid);
            return "添加成功";
        }
        [HttpGet]
        [Authorize]
        public string DiffCar(int goodId)
        {
            //使用本地缓存保存登录用户浏览商品记录(多个商品)
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            //每个用户的Key
            var key = "car_" + userId;

            //添加一个购物车商品 
            var count = _redis.HashDecrement(key, goodId);
            //减少之后如果是0 就删掉
            if (count == 0)
            {
                _redis.HashDelete(key, goodId);
            }
            return "减少成功";
        }
        [HttpGet]
        [Authorize]
        public string DeleteCar(int goodid)
        {
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            var key = "car_" + userId;
            _redis.HashDelete(key, goodid);
            return "删除成功";
        }
        [HttpGet]
        [Authorize]
        public List<GetCarModel> GetCar()
        {
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            var key = "car_" + userId;
            var data = _redis.HashGetAll(key);
            var list = new List<GetCarModel>();
            foreach (var item in data)
            {
                //通过商品Id查询 商品详细信息
                var good = _db.Goods.FirstOrDefault(x => x.Id == (int)item.Name);
                if (good != null)
                {
                    list.Add(new GetCarModel()
                    {
                        GoodId = (int)item.Name,
                        Count = (int)item.Value,
                        Name = good.Name,
                        Price = good.Price,
                        Cover = good.Cover
                    });
                }
            }
            return list;
        }
        [HttpGet]        
        public string AddKeyWord(string keyword)
        {
            var key = "hotkey";
            _redis.SortedSetIncrement(key, keyword, 1);
            return "添加成功";
        }
        [HttpGet]
        public List<GetKeyWord> GetKeyWord()
        {
            var key = "hotkey";
            var data = _redis.SortedSetRangeByRankWithScores(key, 0, 9, Order.Descending);
            var list = new List<GetKeyWord>();
            foreach (var item in data)
            {
                list.Add(new Models.GetKeyWord()
                {
                    Keyword=item.Element,
                    Count=item.Score
                });
            }
            return list;
        }
        [Authorize]
        [HttpGet]
        public string FollowUser(int followUserId)
        {
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            var key = "follow_" + userId;
            _redis.SetRemove(key, followUserId);
            return "取消关注成功";
        }
        public List<int> FollowList(int userId)
        {
            var key = "follow_" + userId;
            var list = _redis.SetMembers(key);
            return list.Select(x => (int)x).ToList();
        }
        public List<int> IntersectUserList(int userId2)
        {
            var key = "follow";
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            var list = _redis.SetCombine(SetOperation.Difference,key+userId,key+userId2);
            return list.Select(x => (int)x).ToList();
        }
        [HttpGet]
        public List<int> GetFollowUserListUnion(int userId1, int userId2)
        {
            var key = "follow_";
            var data = _redis.SetCombine(SetOperation.Union, key + userId1, key + userId2);
            return data.Select(x => (int)x).ToList();
        }
        [HttpGet]
        public List<int> GetFollowUserListDifference(int userId1, int userId2)
        {
            var key = "follow_";
            //求差集
            var data = _redis.SetCombine(SetOperation.Difference, key + userId1, key + userId2);
            return data.Select(x => (int)x).ToList();
        }
    }
}
